using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Common.Pool
{
    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="T">target</typeparam>
    public class ObjectPool<T> : ObjectPoolBase, IObjectPool<T> where T : class
    {
        private PoolObject<T> template;
        private Queue<PoolObject<T>> unUsedQueue;
        private Dictionary<int, PoolObject<T>> allSpawnDic;
        public int RemainCount { get { return unUsedQueue.Count; } }
        int AllCloneCount = 0;//用于记录所有克隆的对象总数
        public ObjectPool(PoolObject<T> obj)
        {
            this.template = obj;
            unUsedQueue = new Queue<PoolObject<T>>();
            allSpawnDic = new Dictionary<int, PoolObject<T>>();
        }
        public PoolObject<T> SpawnObj()
        {
            if (unUsedQueue.Count > 0)
            {
                PoolObject<T> obj1 = unUsedQueue.Dequeue();
                obj1.OnSpawn();
                obj1.isUsed = true;
                return obj1;
            }
            PoolObject<T> obj = Clone();
            obj.OnSpawn();
            obj.isUsed = true;
            return obj;
        }
        public void RecycleObj(PoolObject<T> item)
        {
            if (item.isUsed)
            {
                item.OnRecycle();
                item.isUsed = false;
                unUsedQueue.Enqueue(item);
            }
        }
        public void RecycleObj(int key)
        {
            if (allSpawnDic.ContainsKey(key))
            {
                var item = allSpawnDic[key];

                if (item.isUsed)
                {
                    item.OnRecycle();
                    item.isUsed = false;
                    unUsedQueue.Enqueue(item);
                }
            }
        }
        public void RecycleObjs(List<PoolObject<T>> items)
        {
            foreach (var item in items)
            {
                RecycleObj(item);
            }
        }
        public void RecycleObjs(List<int> keys)
        {
            foreach (var key in keys)
            {
                RecycleObj(key);
            }
        }
        public override void ReleaseUnUsed()
        {
            foreach (var item in unUsedQueue)
            {
                allSpawnDic.Remove(item.Id);
                item.OnDestory();
            }
            unUsedQueue.Clear();
        }
        public override void Destory()
        {
            foreach (var item in allSpawnDic)
            {
                item.Value.OnDestory();
            }
            unUsedQueue.Clear();
            allSpawnDic.Clear();
        }
        private PoolObject<T> Clone()
        {
            PoolObject<T> obj = template.Clone();
            obj.Id = AllCloneCount++;
            allSpawnDic.Add(obj.Id, obj);
            return obj;
        }
        public static ObjectPool<T> Creat(PoolObject<T> obj)
        {
            return new ObjectPool<T>(obj);
        }
    }
    public interface IObjectPool<T> where T : class
    {
        PoolObject<T> SpawnObj();
    }
    public abstract class ObjectPoolBase
    {
        public abstract void ReleaseUnUsed();
        public abstract void Destory();
    }
}
